\documentclass[a4paper,10pt,titlepage]{article}
\usepackage[paperwidth=180mm,paperheight=285mm,left=1.5cm,top=3cm,right=0.5cm,bottom=1cm,head=2.0cm,includefoot]{geometry}
\usepackage[a4,frame,center,noinfo,horigin=-0.75in]{crop}
\usepackage[utf8]{inputenc}
\usepackage[spanish,activeacute]{babel}
\usepackage{fancyhdr}
\usepackage[T1]{fontenc}
\usepackage{graphicx}
\usepackage{bookman}
\usepackage{amsmath}
\usepackage{color}
\usepackage{longtable}
\usepackage{booktabs}
\usepackage{ulem}
\usepackage[pdfborder={0 0 0 0}]{hyperref}
\usepackage{fixltx2e}
\usepackage{array}
\usepackage{float}
\restylefloat{table}
\usepackage{t1enc}
\usepackage{textcomp}
\usepackage{marvosym}
\usepackage{latexsym}
\usepackage{amssymb}
\usepackage{hyperref}
\usepackage{pdfpages} % to import PDF pages
\usepackage{xcolor}
\usepackage{rotating}
\usepackage{listings}
\newcommand{\gsubitem}{\subitem{$-$}}

\makeatletter
\makeatother
\title{Archivos Ubicuos - Manual Técnico}
\author{Pereira, Fernando Roque\\
	\texttt{91610}
	\and
	Reale, Tomás\\
	\texttt{92255}
	\and
	Zapico, Rodrigo\\
	\texttt{93272}}
\date{Junio 2013}

\newpage

\begin{document}
% cuerpo del documento

\pagestyle{fancy}
\lhead{75.42 Taller de Programación I - Veiga \newline Archivos Ubicuos \newline Manual Técnico}
\lfoot{Grupo 1}
\rfoot{ P\'agina \thepage \hspace{0.5pt}}
\cfoot{$1^{er}$ Cuatrimestre 2013}
\maketitle
\newpage
\tableofcontents
\newpage

\section{Requerimientos de software}
\begin{itemize}
 \item Sistema operativo Linux, preferentemente Ubuntu, donde el sistema fue testeado
 \item Compilador de C++, preferentemente g++
 \item Librería gráfica gtkmm-2.4 para la GUI
 \item Cualquier IDE que soporte desarrollo en lenguaje C++. Nuestra recomendación es Eclipse, al cual pueden agregarsele 
 plugins para el debugging del mismo, como así también para el control de versiones
\end{itemize}
\newpage

\section{Descripción}
La división del modelo es bastante lógica. En cada división se encuentra todo lo relativo a cada una de las aplicaciones 
mencionadas a continuación. Sólo resta aclarar, que la división Common posee todo lo relativo a archivos que se 
utilizan en más de una aplicación a la vez, a saber, sockets, delta encoding, parseo de archivos properties, etc, y se 
explicará en la sección correspondiente.

\subsection{Aplicaciones del sistema}
Existen 4 aplicaciones fundamentales:
\begin{itemize}
 \item Aplicación Cliente: Es la aplicación que todo usuario que desee sincronizar sus archivos debe poseer. Esta se 
 comunica con el server mediante el uso de sockets. Posee, opcionalmente, una interfaz gráfica para su configuración.
 \item Aplicación Servidor: Esta aplicación es la encargada de atender a los distintos clientes y de mantener una versión 
 actualizada de cada archivo a sincronizar, discriminados por usuario. Posee una interfaz gráfica para su inicio y 
 configuración.
 \item Aplicación Monitor: GUI utilizada para la configuración de la aplicación Servidor. Se utiliza para la administración 
 de usuarios, para iniciar y finalizar la aplicación servidor y para obtener reporte gráfico del tráfico de bytes en la red.
 \item Aplicación MonitorCliente: GUI utilizada para la configuración de la aplicación cliente, los cuales deben especificar 
 nombre de usuario y contraseña, intervalo de polling, directorio a sincronizar, IP y puerto del servidor. Esta configuración 
 se basa en escritura y lectura (por parte del Cliente) de archivos properties.
\end{itemize}

\subsection{Esquema del Sistema}
Este sistema se basa en una arquitectura Cliente-Servidor, donde cada cual posee un módulo de interfaz gráfica mediante el 
cual es posible interactuar con el usuario. Hay 5 divisiones básicas:
\begin{itemize}
 \item Cliente
 \item Servidor
 \item Common
 \item Monitor
 \item MonitorCliente
\end{itemize}

\newpage

\section{Módulo Cliente}
Este módulo debe instalarse en la máquina del usuario que desea sincronizar sus archivos. Básicamente, luego de una 
configuración y el inicio del programa, realiza un polling inicial al repositorio local configurado por el usuario, 
recibe del server la lista de archivos que posee, sincroniza con el server, y luego, cada cierto intervalo de tiempo, 
realizo un nuevo polling al repositorio local para verificar cambios hechos por el cliente.

Los objetos principales son: 
\begin{itemize}
 \item Cliente: Es el objeto principal de la aplicación y se encarga de conectar todos los módulos que conforman a la misma.
 Almacena nombre de usuario, contraseña, intervalo de polling, y es el responsable de iniciar las acciones, tanto de
 polling como de ejecución de comandos para sincronizar los archivos con el server
 \item FilePoller: Esta entidad es el encargado de realizar el polling al repositorio local y guardar las modificaciones que 
 se encuentran durante este proceso
 \item FileSyncHandler: Esta entidad es la encargada de las actualizaciones propiamente dichas en el repositorio local. Es 
 decir, se encarga de crear archivos nuevos correspondientes, borrarlos, actualizar el índice, en base al resultado lógico 
 de la sincronización con el server. Además se encarga del merge inicial entre la lista de archivos del servidor y los 
 archivos actuales en el repositorio local
 \item Diferencia: Este entidad es la clase madre de una jerarquía de diferencias, las cuales representan todos los casos 
 posibles de diferencias que puede haber entre el repositorio local y el servidor
 \item NotificationListener: Básicamente, este objeto permanece a la escucha de notificaciones por parte del server, en un 
 puerto determinado, diferente por el que se comunican el cliente y el servidor para manejar las diferencias propias
\end{itemize}

\subsection{Objeto Cliente}
Nuclenado a todos los objetos que forman parte de la aplicación, esta entidad tiene como atributos al FilePoller, al 
NotificationListener, al FileSyncHandler, al indice actual del repositorio local, como así también guarda información 
pertinente a la cuenta del usuario actual, como por ejemplo, su nombre de usuario y contraseña.

Partiendo del inicio del programa, este objeto realiza la sincronización inicial con el servidor, realizando un polling 
inicial al repositorio local mediante el FilePoller, captando las diferencias y, luego de loggearse correctamente, 
enviarles los archivos nuevos y borrados al server. Una vez que éste último le envía la lista de archivos que posee, el 
Cliente llama al FileSyncHandler para que realice un merge entre ambos repositorios, obteniendo nuevas diferencias. Estas 
últimas diferencias pueden ser, un archivo nuevo en el server, un archivo borrado o uno modificado. Luego de la 
sincronización, el cliente, en base al intervalo de polling que posee, entra en un loop el cual procede a, manejar las 
notificaciones entrantes, y realizar el polling local correspondiente.

\subsection{Objeto FilePoller}
Este objeto en cuestión tiene como atributo varias listas. Entre ellas, puede verse una lista de archivos nuevos, otra de 
archivos borrados y otra de hashes viejos de la data de los archivos. Estas listas cumplen un determinado rol en la 
sincronización inicial entre el cliente y el server. Una vez que finaliza, las primeras dos no son más necesarias, y solo se 
trabajará con una lista de diferencias general que se actualiza en cada polling. El cliente luego toma esta lista creada por 
el poller y ejecuta los comandos correspondientes a fin de sincronizar los repositorios.

Para realizar el polling, primero se leen todos los archivos que se encuentran en el directorio a sincronizar, mediante las 
llamadas opendir(), readdir() y closedir() provistas por el sistema operativo en el header ``dirent.h''. Una vez leidos todos 
los archivos del directorio, se guardan en una lista que los ordena alfabéticamente (tanto en el cliente como en el server, 
se guardan los nombres de los archivos alfabéticamente, en listas e incluso en los índices locales).
Se inicia un merge entre lo que se lee en el directorio con lo que ya se poseía anteriormente en el índice local, a fin de 
corroborar diferencias. Si el nombre de los archivos son iguales, se compara fecha de modificación, en caso de que difieran, 
se comparan los hash, tanto del archivo en el repo como el guardado en el índice, para corroborar un cambio. Esto generaría 
una diferencia del tipo DiferenciaModifiedFile, la cual será explicada en secciones posteriores. En caso de que exista un 
archivo en el repo, con un nombre ``más chico'' que el que se encuentre próximo en el índice, entonces se crea una diferencia 
del tipo DiferenciaNewFile. Por último, si existe en el índice actual un nombre de archivo menor al próximo en el repo, 
eso significa que el user borró el archivo en cuestión y es necesario eliminarlo del índice y notificar al server. Esto se 
logra mediante la diferencia de tipo DiferenciaErasedFile.
Luego de terminar con el merge, la lista de diferencias general queda actualizada, y una vez finalizado el proceso, el 
cliente pide esta lista a fin de notificar todos los cambios al server.

\subsection{Objeto FileSyncHandler}
Esta entidad es la encargada de modificar el repositorio local en base a los cambios que se producen en la sincronización. 
Para ello, provee una interfaz que comprende crearArchivo() en el repo, borrarArchivo(), borrarTodo() para el caso que se 
haya borrado todo en el servidor y no existan archivos nuevos en el repo local, crear backUp(), el cual crea una copia de 
un archivo que había entrado en conflicto, debido a que el user intentó modificar una versión obsoleta del mismo.
Además, posee un método llamado mergearRepos(), el cual es el encargado de tomar la lista de archivos que nos provee el 
server apenas el cliente se loguea, tomar el índice actual del repositorio local, y crear las diferencias encontradas en los 
mismos. Una vez logrado esto, la información de las diferencias queda guardada en una lista de diferencias general, teniendo 
la misma lógica que el FilePoller en este caso.
Sin embargo, en este caso, las diferencias cumplen un rol diferente. Para el caso del polling inicial, se crean diferencias 
tal que el flujo de información debe ir desde el Cliente al Servidor. Para el caso de mergearRepos() actual, se crean 
diferencias tal que el flujo de información va del Servidor al Cliente.
Por último, este objeto es el encargado de actualizar el índice local ante cada diferencia ejecutada.

\subsection{Objeto Diferencia}
Se creó una jerarquía de diferencias, las cuales saben crear su comando para enviar al server (o que sirve para ejecutar 
el comando de la diferencia correcto mediante el ClientCommandInterpreter).
Básicamente, todas las diferencias heredan de una única clase Diferencia, madre, que posee un método virtual puro. Este 
método debe ser implementado por todas las diferencias hijas, a fin de ejecutarse correctamente la sincronización.
Hay varias hijas diferencia, y cada una de ellas hace referencia a si el flujo se información viaja desde el cliente al 
servidor o del servidor al cliente. La única diferencia se da en la DiferenciaModifiedFile, la cual dentro posee la lógica 
necesaria, mediante el DeltaEncoding, de saber a qué lado viaja la información y la data de los archivos modificados. A 
continuación un diagrama que refleja lo descrito:

\subsection{Objeto NotificacionListener}
Este objeto es iniciado por el objeto Cliente, y consiste en correr en un hilo aparte un módulo que escucha constantemente 
determinado puerto a la espera de notificaciones que envía el servidor.
Básicamente, posee como atributo una cola de notificaciones, pasada por referencia, en la cual se insertan todos los mensajes 
de notificación que le va llegando. A medida que van llegando, en el flujo principal, el objeto Cliente obtiene dichas 
notificaciones y las ejecuta, tomando como modelo el patrón Productor-Consumidor.
Al ser un hilo aparte, para soportar multithreading, la estructura de datos utilizada fue una Cola Bloqueante, la cual hace 
uso de un Mutex para que los datos no sean corrompidos por llamadas de hilos diferentes.

\newpage

\section{Módulo Servidor}
Éste módulo debe instalarse en la máquina utilizada como servidor, y debe mantenerse corriendo constantemente ya que es la 
aplicación a través de la cual clientes pueden conectarse y sincronizar sus archivos. \\
En pocas palabras, al iniciarse el programa servidor se comienza a escuchar en un puerto predeterminado, que debe haber
sido configurado previamente mediante la aplicación monitor. A medida que acepta conexiones, identifica a los usuarios, 
y en caso de que se provea un usuario y contraseña correctos los agrega a una lista de usuarios conectados, los cuales a
su vez poseen una lista con todos los devices desde los cuales se encuentra conectado cada usuario.\\
Una vez online un usuario, el servidor se limita a recibir comandos mediante el comunicador que lo comunica con el usuario 
y ejecutarlos, eventualmente enviando una respuesta en caso de que sea necesario. Además, al detectarse un cambio en un device,
se notifica a todos los demás devices del mismo usuario que se hallen conectados.\\
Los objetos principales son:
\begin{itemize}
 \item Jerarquía de clases ServerCommand: Consiste en una jerarquía de functors donde el padre es ServerCommand. Cada uno
 se encarga de ejecutar, mediante el método execute(), el comando correspondiente a su nombre. En la sección correspondiente
 se detalla cada comando y su función.
 \item ServerCommandInterpreter: Se trata de una clase dedicada exclusivamente a obtener el comando a ser ejecutado, dada
 una constante que lo identifica. La misma se recibe como un mensaje de parte del cliente.
 \item Device: representa un device conectado al servidor. Cada device corre en un thread independiente, y en encarga de 
 recibir los mensajes enviados desde el cliente, identificar el comando mediante el ServerCommandInterpreter, setear los parámetros
 que sean necesarios y encolarlo para que el usuario correspondiente ejecute el comando cuando corresponda.
 \item Usuario: Representa un usuario conectado al servidor. Cada usuario puede estar conectado desde varios devices, por
 lo que ésta clase posee una lista de todos los devices conectados actualmente. Cada instancia de ésta clase corre en un thread
 independiente. Se encarga de realizar las tareas encomendadas por los distintos devices, y administrar las notificaciones y 
 eventuales desconexiones.
\end{itemize}

\subsection{Jerarquía de clases ServerCommand}
Cada una de éstas clases hereda de ServerCommand e implementa el método abstracto:\\
std::string execute(std::string \&username);
El mismo permite, mediante polimorfismo, definir un comportamiento distinto para cada comando. \\
El retorno de cada comando es el mensaje a ser enviado al cliente, con la aclaración de que, en caso que el retorno 
inicie con la constante NOTIFY definida en const.h del common, se debe iniciar el proceso de notificación además del mensaje
al cliente.\\
Como cada comando recibe distintos parámetros, se define en la clase padre un método parametros(std::string \&p) que debe 
ser llamado antes de la llamada a execute, y setea los parametros como son recibidos del cliente. Cada comando sabe como
parsear sus propios parametros.\\
Los comandos son los siguientes:
\begin{itemize}
 \item GetFilesCommand: Devuelve la lista de archivos, con sus respectivos hashes y fechas de modificación. No recibe parámetros.
 \item GetFileCommand: Devuelve los contenidos del archivo pedido. Recibe como parámetro el nombre del archivo requerido.
 \item TryUpdateUpFileCommand: Cuando un cliente quiere subir una modificación a un archivo ya sincronizado, debe enviar éste
 comando, con el nombre de archivo a modificar y su hash anterior como parámetros, para determinar si el cliente efectuó las
 modificaciones sobre una copia actualizada del archivo, o una copia inválida (no sincronizada). El comando retorna OK o FAIL. 
 En el 2do caso, el cliente deberá realizar un backup de su archivo modificado, y sincronizar con el servidor antes de
 subir una modificación.o un cliente quiere subir una modificación a un archivo ya sincronizado, debe enviar éste
 comando, con el nombre de arch: Escencialmente lo mismo, pero para casos en que se quiere descargar la ultima versión de un 
 archivo. Detecta conflictos (modificaciones locales en la copia del cliente respecto de la del servidor). Notar que en éste caso, 
 el cliente siempre descarga, el comando solo es llamado para determinar si debe hacer un backup antes de descargar.ivo a modificar y su hash anterior como parámetros, para determinar si el cliente efectuó las
 modificaciones sobre una copia actualizada del archivo, o una copia inválida (no sincronizada). El comando retorna OK o FAIL. 
 En el 2do caso, el cliente deberá realizar un backup de su archivo modificado, y sincronizar con el servidor antes de
 subir una modificación.
 \item TryUpdateDownFileCommand: Escencialmente lo mismo, pero para casos en que se quiere descargar la ultima versión de un 
 archivo. Detecta conflictos (modificaciones locales en la copia del cliente respecto de la del servidor). Notar que en éste caso, 
 el cliente siempre descarga, el comando solo es llamado para determinar si debe hacer un backup antes de descargar.
 \item UpdateFileCommand: Al querer realizar la sincronizacion inicial, si se detectan cambios en un archivo entre cliente 
 y servidor, se utiliza éste comando para determinar quien es el emisor y quién el receptor del delta.
 \item UpdateFileEmisorCommand: Si el servidor es emisor, se envía éste comando.
 \item UpdateFileReceptorCommand: En cambio, si es receptor, se envía éste otro.
 \item UpdateFileReceptor2Command: 2da parte del protocolo de sincronización de un archivo en caso de que el receptor sea el
 servidor.
 \item UpdateFileFinishedCommand: Finaliza el protocolo de sincronización de un archivo. Éste comando retorna NOTIFY, 
 con lo cual el servidor debe notificar de las modificaciones a los demas devices conectados.
 \item EraseFileCommand: Elimina un archivo del repositorio. Éste comando retorna NOTIFY, con lo cual el servidor 
 debe notificar de las modificaciones a los demas devices conectados.
 \item UploadFileCommand: Agrega un nuevo archivo al repositorio. Éste comando retorna NOTIFY, con lo cual el servidor 
 debe notificar de las modificaciones a los demas devices conectados.
 \item LogoutCommand: Avisa al servidor que el device que lo envia se desconectará.
\end{itemize}

\newpage

\subsection {Ejecución de un comando}
Desde que un comando es recibido en un device hasta que se contesta, existen varias interacciónes entre distintos objetos
con el fin de determinar que comando debe ejecutarse, en que momento ejecutarlo, si se debe desconectar al device, 
si se debe notificar a los demas, etc. El siguiente diagrama de clases intenta explicar como se relacionan entre si.

 \begin{center} \includegraphics[scale=0.5]{DiagramaServer.png} \end{center}

Cada vez que llega un mensaje a un device, éste se encola en una lista de devices con tareas pendientes. El usuario a su vez
controla ésta lista y 'autoriza' a un device a la vez a ejecutar sus tareas pendientes, indicandoselo mediante una llamada
al método ejecutarTarea del device. Luego controla si debe notificar o desconectar algun device, y selecciona un nuevo device
con tareas pendientes para ejecutar, iniciando de nuevo el ciclo.
\subsection{Syslog}
Tanto la aplicación cliente como servidor usan syslog para loggear ocurrencias importantes, ya sean mensajes de error o mensajes informativos.\\
Estos mensajes se guardan en `/var/log/user.log`.\\
Ejemplo :\\ 
Jun 24 13:07:40 tom-laptop monitor: Servidor Actualizado\\
Jun 24 13:07:53 tom-laptop monitor: no se pudo establecer conexion\\

Aparece primero la fecha y hora, luego el usuario que ejecutó el programa, seguido del nombre de la aplicación en si, y el mensaje loggeado.

\newpage

\section{Módulo Monitor}
 \begin{center} \includegraphics[scale=0.3]{Monitor.png} \end{center}
\subsection{Comunicación grafico de bytes}

Para poder obtener el tamaño del repositorio del servidor instante a instante, la aplicación monitorserver requeria datos de la aplicacion server.\\
Para lograr esto, se decidio que se comuniquen por ` loopback (127.0.0.1) `, a traves de un puerto dedicado solamente a esta tarea ( puerto : 10000 )\\
Esto se hizo asi ya que estas 2 aplicaciones corren en la misma maquina, y para no tener que tener en cuenta problemas de concurrencia entre 2 procesos
intentanto acceder al mismo archivo.\\
Es posible agregar una funcionalidad nueva a la aplicación monitor, con pocos cambios.\\
En vez de comunicarse por loopback, se podria comunicar via una ip convencional ( manteniendo el mismo puerto ). De esta forma, se podria observar
el grafico desde una ubicación distinta a en la que corre la aplicación servidor.\\
En `common/const.h`:\\
// ******************* Const server ******************\\
\#define PATH "Path"\\
\#define IPEsp "127.0.0.1"\\
\#define PuertoEsp 10000\\
//****************************************************\\

\section{Módulo MonitorCliente}

\newpage

\section{Módulo Common}

\subsection{Mensajes Cliente/Servidor}

Los mensajes intercambiados entre el Cliente y el Servidor son:

Del cliente hacia el servidor:
\begin{itemize}
 \item `LOGIN`
 \item `GET-FILE-LIST`
 \item `GET-FILE`
 \item `UPLOAD`
 \item `TRY-UPDATE-UP`
 \item `TRY-UPDATE-DOWN`
 \item `UPDATE`
 \item `UPDATERECEPTOR`
 \item `UPDATERECEPTOR2`
 \item `UPDATEEMISOR`
 \item `UPDATEOK`
 \item `ERASE`
 \item `LOGOUT`
\end{itemize}

Del servidor hacia el cliente:
\begin{itemize}
 \item `OK`
 \item `FAIL`
 \item `FILE-LIST`
 \item `NOTIFY`
 \item `EMISORDELTA`
 \item `RECEPTORDELTA`
 \item `DELTA`
\end{itemize}

Del servidor hacia el client , notificaciones 
\begin{itemize}
 \item `ERASED`
 \item `NEW`
 \item `UPDATED`
\end{itemize}

\subsection{Diseño Sockets}
 \begin{center} \includegraphics[scale=0.3]{Sockets.png} \end{center}
La clase Socket encapsula algunas funcionalidades de la libreria `<sys/socket.h>`.\\
SocketCliente y SocketServer terminan de completar todas las funcionalidades.\\
La clase Comunicador es la encargada del manejo del protocolo de comunicacion del sistema, además ser donde se verifica la integridad de los mensajes via HMAC.

\newpage

\subsection{Integridad HMAC}
El hash usado para HMAC es MD5. Es posible cambiar este hash por otros siempre que se actualicen las longitudes esperadas de los hashes en HMAC.h.
Toda la lógica del HMAC esta encapsulada en la clase HMAC, y esta se usa dentro de la clase Comunicador.\\
En otras palabras, todo lo que implica HMAC es transparente a las clases fuera de Comunicador , salvo por el hecho que si la integridad del mensaje se ve
comprometida, se lanza una excepción.\\

Se define:
\begin{itemize}
 \item B = tamaño del bloque = 64
 \item L = tamaño del hash = 16
 \item ipad = el byte 0x36 repetido B veces.
 \item opad = el byte 0x5C repetido B veces.
\end{itemize}

El algoritmo HMAC es: H(K XOR opad, H(K XOR ipad, texto))
\begin{itemize}
 \item (0) Si la clave > 64, hashearla y usar eso como clave
 \item (1) appendear 0 a la clave hasta tener un string de tamaño B
 \item (2) XOR ( or exclusivo ) entre (1) e ipad
 \item (3) appendear (2) al texto
 \item (4) hashear (3)
 \item (5) XOR ( or exclusivo) entre (1) y opad
 \item (6) appendear (4) con (5)
 \item (7) hashear (6) y mostrar resultado
\end{itemize}

El resultado no es de 16 bytes, sino de 32, ya que se pasa a hexadecimal.

\newpage

\subsection{Protocolo Recepción/Envio por Comunicador}
 \subsubsection{int Comunicador::enviarMensaje(std::string \&m)}
  El algoritmo que usa el Comunicador para enviar un mensaje es:\\
  \begin{itemize}
  \item Calcular longitud mensaje
  \item Calcular HMAC del mensaje
  \item Genererar un string S = LongitudMensaje + ` ` + mensaje + hmacMensaje
  \item Calcular longitud de S
  \item Enviar longitud de S a traves de la red
  \item Entrar en un ciclo enviando S a traves de la red hasta que se haya enviado todo.
  \end{itemize}
  \subsubsection{int Comunicador::recibirMensaje(std::string\& buffer)}
  El algoritmo que usa el Comunicador para recibir un mensaje es:\\
  \begin{itemize}
  \item Recibir longitud mensaje
  \item Entrar en un ciclo hasta haber recibido todo el mensaje.
  \item Parsear mensaje recibido, obteniendo la data y el hmac de la data
  \item Calcular HMAC de la data
  \item Comparar HMAC calculado con HMAC recibido. Si son distintos lanzar excepción
  \item Devolver la data en buffer
  \end{itemize}

\newpage

\subsection{Delta Encoding}
\subsubsection{Diagrama}
 \begin{center} \includegraphics[scale=0.3]{DeltaEncoding.png} \end{center}
\subsubsection{Secuencia de ejecución}
\lstinputlisting{secuenciaDeltaEncoding}

\newpage

\section{Código Fuente}

\end{document}